8386546: Fix race when reserving memory with NUMA interleaving on Windows - #31507
roberttoyonaga wants to merge 3 commits into
Conversation
|
👋 Welcome back roberttoyonaga! A progress list of the required criteria for merging this PR into |
|
@roberttoyonaga This change now passes all automated pre-integration checks. ℹ️ This project also has non-automated pre-integration requirements. Please see the file CONTRIBUTING.md for details. After integration, the commit message for the final commit will be: You can use pull request commands such as /summary, /contributor and /issue to adjust it as needed. At the time when this comment was updated there had been 245 new commits pushed to the
As there are no conflicts, your changes will automatically be rebased on top of these commits when integrating. If you prefer to avoid this automatic rebasing, please check the documentation for the /integrate command for further details. As you do not have Committer status in this project an existing Committer must agree to sponsor your change. Possible candidates are the reviewers of this PR (@ashu-mehra, @tstuefe) but any other Committer may sponsor as well. ➡️ To flag this PR as ready for integration with the above commit message, type |
|
@roberttoyonaga The following label will be automatically applied to this pull request:
When this pull request is ready to be reviewed, an "RFR" email will be sent to the corresponding mailing list. If you would like to change these labels, use the /label pull request command. |
|
The total number of required reviews for this PR has been set to 2 based on the presence of this label: |
c343094 to
9174be5
Compare
9174be5 to
e492857
Compare
Webrevs
|
|
Hi Robert, I intend to review this as well, but it'll have to wait until next week. |
| char* os::win32::convert_to_reserved(PlaceholderRegion region, int numa_node) { | ||
| guarantee(is_VirtualAlloc2_supported(), "convert_to_reserved requires VirtualAlloc2"); | ||
| assert(!region.is_empty(), "Region cannot be empty"); | ||
| assert(is_aligned(region.base(), os::vm_page_size()), "Region base should be page-aligned"); |
There was a problem hiding this comment.
Shouldn't the region.base() be aligned to allocation granularity as it is passed to VirtualAlloc2 which expects BaseAddress to be a multiple of the system allocation granularity.
There was a problem hiding this comment.
Yes that's a good point. I have updated it to assert(is_aligned(region.size(), os::vm_allocation_granularity())
There was a problem hiding this comment.
hmm, if the PlaceholderRegion's base should be aligned to allocation granularity, then shouldn't split_memory require that the offset be also aligned to allocation granularity? After all, the PlaceholderRegion's base depends on the offset provided split_memory.
I also wonder if we should move this assert to Placeholder's constructor, because it looks like the base must always be aligned to allocation granularity.
There was a problem hiding this comment.
I think you're right. I've moved the asserts into the Placeholder constructor.
However, offset doesn't always need to be aligned to allocation granularity. For example, at the end of reserve_with_numa_placeholder when the split consumes the entire remaining Placeholder region. But it's easy to handle this special case, then assert afterward.
| reserveTimer.milliseconds(), reserveTimer.ticks()); | ||
| bool use_numa_interleaving = (UseNUMAInterleaving && !UseLargePages); | ||
| if (use_numa_interleaving) { | ||
| if (is_VirtualAlloc2_supported()) { |
There was a problem hiding this comment.
I think this block should be inside reserveTimer() scope, like:
elapsedTime reserveTimer;
if (is_VirtualAlloc2_supported()) {
...
} else {
...
}
if (Verbose && Print...) {
...
}
There was a problem hiding this comment.
I think you are right. I have widened the scope of the timer. Thanks!
| // Double convert | ||
| char* reserved = os::win32::convert_to_reserved(region); | ||
| ASSERT_EQ(reserved, region.base()); | ||
| reserved = os::win32::convert_to_reserved(region); |
There was a problem hiding this comment.
It is not clear what the double convert is expected to do. Would it fail silently or crash?
There was a problem hiding this comment.
This test should crash and produce the error text: "...Failed to convert placeholder...". I've added a comment there for clarity.
ashu-mehra
left a comment
There was a problem hiding this comment.
Thanks for addressing the comments, lgtm
|
Thank you for the reviews! /integrate |
|
Going to push as commit 376ecc5.
Your commit was automatically rebased without conflicts. |
|
@roberttoyonaga Pushed as commit 376ecc5. 💡 You may see a message that your pull request was closed with unmerged commits. This can be safely ignored. |
Summary
Previously on Windows Hotspot used the following race-y pattern to reserve a virtual memory region and divide it up among NUMA nodes:
See
allocate_pages_individually.VirtualAlloc2 (available since Windows version 1803) removes the need for this race-y code by introducing "placeholders". Placeholders allow for reserving regions, and later splitting them up while still holding the reservation.
This is a scoped-down version of JDK-8376561 and #30270 limited to the changes required to eliminate the NUMA race. This is the 2nd change in a series of changes that take advantage of VirtualAlloc2 to replace races in Windows code. The preceding change was JDK-8385586.
Divergences from JDK-8376561 / #30270 :
os::Placeholder API has been moved intoos::win32::in order to constrain the scope of changes to Windows code only.Notes
reserve_placeholder_memory,split_memory, andconvert_to_reservedcould have been made internal helper functions in os_windows.cpp. However, I added them toos::win32::so that they could be more thoroughly unit tested.Testing:
make test TEST=gtest:os_windows.placeholder_numa_reserve_commit GTEST="VM_OPTIONS=-XX:+UseNUMAInterleaving"make test TEST=gtest:osTested locally on Windows with multiple NUMA nodes and also without multiple NUMA nodes.
Progress
Issue
Reviewers
Reviewing
Using
gitCheckout this PR locally:
$ git fetch https://git.openjdk.org/jdk.git pull/31507/head:pull/31507$ git checkout pull/31507Update a local copy of the PR:
$ git checkout pull/31507$ git pull https://git.openjdk.org/jdk.git pull/31507/headUsing Skara CLI tools
Checkout this PR locally:
$ git pr checkout 31507View PR using the GUI difftool:
$ git pr show -t 31507Using diff file
Download this PR as a diff file:
https://git.openjdk.org/jdk/pull/31507.diff
Using Webrev
Link to Webrev Comment